/**
 * phi
 */


/**
 * elm と一致する要素を削除
 */
Array.prototype.erase = function(elm) {
    var index  = this.indexOf(elm);
    this.splice(index, 1);
    return this;
};

// ブラウザ対応 Audio 拡張子取得
var AUDIO_EXT = (function(){
    var ext = "";
    var audio = new Audio();
    if (audio.canPlayType("audio/ogg") == "maybe") { ext="ogg"; }
    if (audio.canPlayType("audio/mp3") == "maybe") { ext="mp3"; }
    if (audio.canPlayType("audio/wav") == "maybe") { ext="wav"; }
    return ext;
})();




// 十字キーを角度に変換するルックアップテーブル
var ARROW_TO_ANGLE_TABLE = {
    // 上下左右
    0x0001: 270,    // 下
    0x0002:   0,    // 右
    0x0004:  90,    // 上
    0x0008: 180,    // 左
    // 斜め
    0x0006:  45,    // 右上
    0x0003: 315,    // 右下
    0x000c: 135,    // 左上
    0x0009: 225,    // 左下
    // 三方向同時押し対応
    // 想定外の操作だが対応しといたほうが無難
    0x000e:  90,    // 右上左
    0x000d: 180,    // 上左下
    0x000b: 270,    // 左下右
    0x0007:   0,    // 下右上
};

var FRAME_RATE      = 60;
var PLAYER_SPEED    = 1;
var PLAYER_RADIUS   = 2;

var BOMB_TIMER = 300;
var CRASH_TIMER = 60;




// おまじない
enchant();

var game = null;
var crash_se = null;


/**
 * 
 */
window.onload = function()
{
    game = new Game(640, 640);
    game.fps = FRAME_RATE;
    
    // ボム用
    crash_se = new Audio("se/bom." + AUDIO_EXT);
    
    game.onload = function() {
        game.score = 0;
        game.enemyTableIndex = 0;
        game.crashList = [];
        
        var scene = new Scene3D();
        scene.backgroundColor = "rgba(100, 100, 100, 1.0)";
        
        // ライト
        var light = new DirectionalLight();
        scene.setDirectionalLight(light);
        
        // カメラ
        var camera = new Camera3D();
        camera.x = 0;
        camera.y = 230;
        camera.z = 230;
        camera.centerX = 0;
        camera.centerY = 0;
        camera.centerZ = 0;
        /*
        camera.x = 0;
        camera.y = 10;
        camera.z = 40;
        /**/
        scene.setCamera(camera);
        
        // 床
        var floor = new Floor(100, 100, 17, 17);
        floor.x = 0;
        floor.y =-2;
        floor.z = 0;
        floor.mesh.texture.ambient = [1.0, 1.0, 1.0, 1.0];
        scene.addChild(floor);
        
        // プレイヤー
        var player = new Player();
        scene.addChild(player);
        
        game.rootScene.addEventListener("enter", function(){
            game.frame = 0;
        });
        
        game.rootScene.addEventListener("enterframe", function(e) {
            
            if (game.frame % 60 == 0) {
                game.score += (game.enemyTableIndex+1) * 10;
            }
            
            createEnemyFuncTable[game.enemyTableIndex]();
            
            if (game.frame % 1200 == 0 && game.enemyTableIndex < 4) {
                console.log("level : ", game.enemyTableIndex+1);
                game.enemyTableIndex += 1;
            }
            
            // プレイヤーと敵との衝突判定
            for (var i=0; i<game.crashList.length; ++i) {
                var crash = game.crashList[i];
                if (isCollision(game.player, crash) == true) {
                    console.log("hit!!");
                    game.end(game.score, "Game Over!! あなたのスコアは " + game.score + " です.");
                }
            }
        });
        
        // 2D
        var score_label = new Label();
        game.rootScene.addChild(score_label);
        score_label.moveTo(12, 20);
        score_label.color = "white";
        score_label.addEventListener(Event.ENTER_FRAME, function(){
            this.text = "SCORE : " + game.score;
        });
    }
    
    game.start();
};

var createEnemyLevel01 = function()
{
    if (game.frame%240 == 0) {
        var bomb = new Bomb(Math.random()*100-50, 100, Math.random()*100-50);
        game.currentScene3D.addChild( bomb );
    }
};

var createEnemyLevel02 = function()
{
    if (game.frame%120 == 0) {
        var bomb = new Bomb(Math.random()*100-50, 100, Math.random()*100-50);
        game.currentScene3D.addChild( bomb );
    }
};

var createEnemyLevel03 = function()
{
    if (game.frame%90 == 0) {
        var bomb = new Bomb(Math.random()*100-50, 100, Math.random()*100-50);
        game.currentScene3D.addChild( bomb );
    }
};

var createEnemyLevel03 = function()
{
    if (game.frame%60 == 0) {
        var bomb = new Bomb(Math.random()*100-50, 100, Math.random()*100-50);
        game.currentScene3D.addChild( bomb );
    }
};

var createEnemyLevel04 = function()
{
    if (game.frame%30 == 0) {
        var bomb = new Bomb(Math.random()*100-50, 100, Math.random()*100-50);
        game.currentScene3D.addChild( bomb );
    }
};

var createEnemyLevel05 = function()
{
    if (game.frame%20 == 0) {
        var bomb = new Bomb(Math.random()*100-50, 100, Math.random()*100-50);
        game.currentScene3D.addChild( bomb );
    }
};

var createEnemyFuncTable = [
    createEnemyLevel01,
    createEnemyLevel02,
    createEnemyLevel03,
    createEnemyLevel04,
    createEnemyLevel05,
];



/**
 * プレイヤー
 */
var Player = enchant.Class.create(enchant.gl.primitive.Cube, {
    
    initialize: function() {
        enchant.gl.primitive.Cube.call(this);
        
        this.mesh.setBaseColor([0.25, 0.25, 1.0, 1.0]);
        
        this.x = 0;
        this.y = 0;
        this.z = 0;
        this.radius = PLAYER_RADIUS;
        this.scale(PLAYER_RADIUS, PLAYER_RADIUS, PLAYER_RADIUS);
        
        this.addEventListener("enterframe", function(e) {
            var input = game.input;
            var arrowBit = (input.left << 3) | (input.up << 2) | (input.right << 1) | (input.down << 0);
            var angle = ARROW_TO_ANGLE_TABLE[ arrowBit ];
            if (angle !== undefined) {
                var vx = Math.cos(angle*Math.PI/180) * PLAYER_SPEED;
                var vz =-Math.sin(angle*Math.PI/180) * PLAYER_SPEED;
                this.x += vx;
                this.z += vz;
                
                if (this.x > 50) { this.x = 50; }
                if (this.x <-50) { this.x =-50; }
                if (this.z > 50) { this.z = 50; }
                if (this.z <-50) { this.z =-50; }
            }
        });
        
        game.player = this;
    }
    
});

var Bomb = enchant.Class.create(enchant.gl.primitive.Sphere, {
    initialize: function(x, y, z) {
        enchant.gl.primitive.Sphere.call(this);
        
        this.mesh.setBaseColor([0.25, 0.25, 0.25, 1.0]);
        
        this.x = x; this.y = y; this.z = z;
        this.scale(2, 2, 2);
        this.timer = BOMB_TIMER;
        
        this.addEventListener("enterframe", function(e) {
            this.timer -= 1;
            if (this.y > 0) {
                this.y -= 1;
            }
            
            if (this.timer < 30 && this.timer%3) {
                this.mesh.setBaseColor([0.25, 0.25, 0.25, 0.0]);
            }
            else {
                this.mesh.setBaseColor([0.25, 0.25, 0.25, 1.0]);
            }
            
            
            if (this.timer <= 0) {
                var crash = new Crash(this.x, this.y, this.z);
                game.crashList.push(crash);
                game.currentScene3D.addChild(crash);
                game.currentScene3D.removeChild(this);
            }
        });
    }
});


var Crash = enchant.Class.create(enchant.gl.primitive.Sphere, {
    initialize: function(x, y, z) {
        enchant.gl.primitive.Sphere.call(this);
        
        
        this.mesh.setBaseColor([1.0, 0.25, 0.0, 1.0]);
        
        this.x = x; this.y = y; this.z = z;
        this.radius = 2;
        this.scaleX = this.scaleY = this.scaleZ = this.radius;
        this.timer = CRASH_TIMER;
        
        // クラッシュ SE を再生
        crash_se.volume = 0.5;
        crash_se.play();
        crash_se = new Audio(crash_se.src);
        
        this.addEventListener("enterframe", function(e) {
            this.timer -= 1;
            this.radius += 0.25;
            this.scaleX = this.scaleY = this.scaleZ = this.radius;
            
            // カラー
            this.mesh.setBaseColor([1.0, 0.25, 0.0, this.timer/CRASH_TIMER]);
            this.mesh.setBaseColor([1.0, 0.25, 0.0, this.timer/CRASH_TIMER]);
            
            if (this.timer <= 0) {
                game.crashList.erase(this);
                game.currentScene3D.removeChild(this);
            }
        });
    },
    
    ondrawbefore: function() {
        gl.enable(gl.BLEND);                // ブレンド有効化
        gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA ); // アルファブレンド
        gl.disable(gl.DEPTH_TEST);          // デプスのテストを切っておく
    },
    
    ondrawafter: function() {
        gl.disable(gl.BLEND);           // ブレンド無効化
        gl.blendFunc(gl.ONE, gl.ZERO);  // デフォルトに戻す
        gl.disable(gl.DEPTH_TEST);      // デプスのテストを有効化
    },
});

var isCollision = function(obj0, obj1)
{
    var distance_x  = obj1.x - obj0.x;
    var distance_y  = obj1.y - obj0.y;
    var distance_z  = obj1.z - obj0.z;
    var distance    = Math.pow(distance_x, 2) + Math.pow(distance_y, 2) + Math.pow(distance_z, 2);
    return distance <= Math.pow(obj0.radius + obj1.radius, 2);
};

